﻿using System;
using System.Collections;
using System.Collections.Generic;

/*
 * 2014-9-21
 *  完成链式栈泛型和非泛型的第一个版本
 *  为非泛型添加一个同步链式栈
 */

namespace Ycg.Core
{
    public class LinkStack : IEnumerable
    {
        private LinkNode _topNode;

        public object Pop()
        {
            if (this._topNode == null)
            {
                throw new Exception("No Data.");
            }
            object data = this._topNode.Data;
            this._topNode = this._topNode.NextNode;
            return data;
        }

        public void Push(object data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (this._topNode == null)
            {
                this._topNode = new LinkNode(data);
            }
            else
            {
                this._topNode = new LinkNode(data, this._topNode);
            }
        }

        public IEnumerator GetEnumerator()
        {
            return new LinkStackEnumerator(this._topNode);
        }

        public LinkStack Synchronized(LinkStack linkStack)
        {
            if (linkStack == null)
            {
                throw new ArgumentNullException("linkStack");
            }
            return new SyncLinkStack(linkStack);
        }

        private class LinkStackEnumerator : IEnumerator
        {
            private LinkNode _linkNode;

            public LinkStackEnumerator(LinkNode linkNode)
            {
                this._linkNode = linkNode;
            }

            public object Current
            {
                get
                {
                    object data = this._linkNode.Data;
                    this._linkNode = this._linkNode.NextNode;
                    return data;
                }
            }

            public bool MoveNext()
            {
                return this._linkNode != null;
            }

            public void Reset()
            {
                throw new NotImplementedException();
            }
        }

        private class SyncLinkStack : LinkStack
        {
            private object _obj;
            private LinkStack _linkStack;

            public SyncLinkStack(LinkStack linkStack)
            {
                this._obj = new object();
                this._linkStack = linkStack;
            }

            public new object Pop()
            {
                lock (this._obj)
                {
                    return this._linkStack.Pop();
                }
            }

            public new void Push(object data)
            {
                lock (this._obj)
                {
                    this._linkStack.Push(data);
                }
            }
        }
    }

    public class LineStatck<T> : IEnumerable<T>
    {
        private LinkNode<T> _topNode;

        public T Pop()
        {
            if (this._topNode == null)
            {
                throw new Exception("No Data.");
            }
            T data = this._topNode.Data;
            this._topNode = this._topNode.NextNode;
            return data;
        }

        public void Push(T data)
        {
            if (this._topNode == null)
            {
                this._topNode = new LinkNode<T>(data);
            }
            else
            {
                this._topNode = new LinkNode<T>(data, this._topNode);
            }
        }

        public IEnumerator<T> GetEnumerator()
        {
            return new LinkStatckIEnumeratorGeneric(this._topNode);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return new LinkStatckIEnumeratorGeneric(this._topNode);
        }

        private class LinkStatckIEnumeratorGeneric : IEnumerator<T>
        {
            private LinkNode<T> _linkNode;

            public LinkStatckIEnumeratorGeneric(LinkNode<T> linkNode)
            {
                this._linkNode = linkNode;
            }

            public T Current
            {
                get
                {
                    T data = this._linkNode.Data;
                    this._linkNode = this._linkNode.NextNode;
                    return data;
                }
            }

            public void Dispose()
            {
                throw new NotImplementedException();
            }

            object IEnumerator.Current
            {
                get { throw new NotImplementedException(); }
            }

            public bool MoveNext()
            {
                return this._linkNode != null;
            }

            public void Reset()
            {
                throw new NotImplementedException();
            }
        }
    }
}
